﻿using PBO.Data;
using PBO.Game.BattleClass;
using PokemonBattle.BattleNetwork;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PBO.Game.Img
{
    public class ScreenDownPainter
    {
        public enum SelectedPage : byte
        {
            Index,
            SelectingMove,
            SelectingPM,
            Waiting
        }

        private Battle battle;
        private Bitmap Image;
        private PictureBox withEventsField_picturebox;
        private PictureBox picturebox
        {
            get { return withEventsField_picturebox; }
            set
            {
                if (withEventsField_picturebox != null)
                {
                    withEventsField_picturebox.MouseClick -= picturebox_MouseClick;
                    withEventsField_picturebox.MouseDoubleClick -= picturebox_MouseClick;
                }
                withEventsField_picturebox = value;
                if (withEventsField_picturebox != null)
                {
                    withEventsField_picturebox.MouseClick += picturebox_MouseClick;
                    withEventsField_picturebox.MouseDoubleClick += picturebox_MouseClick;
                }
            }
        }

        private SelectedPage mPage;
        private int mSelectedPMIndex = 1;
        private int mSelectedIndex;
        private bool mClickable;
        private bool mMoved;

        #region event

        public event Action<PlayerBattleMove> PlayerMoved;
        public event EventHandler Escape;
        public event EventHandler Tie;
        public event EventHandler StartShake;
        public event EventHandler StopShake;
        public event Action<Pokemon> ShowPokemonInfo;
        public event EventHandler HidePokemonInfo;

        #endregion

        public ScreenDownPainter(PictureBox pictureboxValue, Battle battleValue, int index)
        {
            picturebox = pictureboxValue;
            this.battle = battleValue;
            this.MyTeam = battleValue.Teams.First(t => t.Id == index);

            picturebox.Image = new Bitmap(256, 192);
            Image = (Bitmap)picturebox.Image;

            mPage = SelectedPage.Waiting;
            Moved = true;
        }

        public void Reset()
        {
            picturebox.Image = new Bitmap(256, 192);
            Image = (Bitmap)picturebox.Image;
            Paint();
        }
        public void Paint()
        {
            if (picturebox.InvokeRequired)
            {
                picturebox.Invoke(new Action(Update));
            }
            else
            {
                try
                {
                    Update();
                }
                catch
                {
                    if (picturebox.Image == null)
                        this.Reset();
                }
            }
        }
        private void Update()
        {
            Graphics graph = Graphics.FromImage(Image);
            try
            {
                switch (Page)
                {
                    case SelectedPage.Index:
#warning en index
                        graph.DrawImageUnscaled(Properties.Resources.Index, 0, 0);
                        graph.DrawImageUnscaled(ImageHelper.GetIndexImage(MyGroup), 0, 0);

                        graph.DrawImageUnscaledAndClipped(SelectedPokemon.Icon, new Rectangle(71, 65, 32, 32));
                        break;
                    case SelectedPage.SelectingMove:
                        graph.DrawImageUnscaled(Properties.Resources.SelectMove, 0, 0);

                        int index = 0;
                        foreach (var move in SelectedPokemon.GetSelMoves())
                        {
                            graph.DrawImageUnscaled(move.Image, MovePoint[index++]);
                        }

                        if (SelectedIndex != 0)
                            graph.DrawImageUnscaled(Properties.Resources.MoveFrame, MovePoint[SelectedIndex - 1]);
                        break;
                    case SelectedPage.SelectingPM:
                        graph.DrawImageUnscaled(Properties.Resources.SelectPokemon, 0, 0);
                        int start = 0;
                        if (MyGroup.Teams.Count > 1 && object.ReferenceEquals(SelectedPokemon, MyGroup.Teams[1].SelectedPokemon.FirstOrDefault()))
                            start = 6;
                        for (int i = 0; i < 6; i++)
                        {
                            Pokemon pm = MyGroup.GetPokemonByIndex(i + start);
                            if (pm == null)
                                break; // TODO: might not be correct. Was : Exit For
                            if (i > 0)
                            {
                                graph.DrawImageUnscaled(Properties.Resources.Pokemon, PokemonPoint[i]);
                            }
                            graph.DrawImageUnscaled(ImageHelper.GetPMImage(pm), PokemonPoint[i]);
                        }

                        if (SelectedIndex != 0)
                            graph.DrawImageUnscaled(Properties.Resources.PokemonFrame, PokemonPoint[SelectedIndex - 1]);
                        break;
                    case SelectedPage.Waiting:
                        graph.DrawImageUnscaled(Properties.Resources.back, 0, 0);
                        break;
                }
            }
            finally
            {
                graph.Dispose();
            }
            picturebox.Refresh();
        }

        public SelectedPage Page
        {
            get { return mPage; }
            set
            {
                if (mPage == SelectedPage.SelectingPM && value != SelectedPage.SelectingPM)
                {
                    if (HidePokemonInfo != null)
                    {
                        HidePokemonInfo(null, EventArgs.Empty);
                    }
                }
                mPage = value;
                mSelectedIndex = 0;
                Paint();
            }
        }
        public int SelectedIndex
        {
            get { return mSelectedIndex; }
            private set
            {
                if (value >= 0)
                {
                    mSelectedIndex = value;
                    Paint();
                }
            }
        }
        public bool Moved
        {
            get { return mMoved; }
            set
            {
                mMoved = value;
                mClickable = !mMoved;
                if (Moved == true)
                {
                    if (StopShake != null)
                    {
                        StopShake(this, EventArgs.Empty);
                    }
                    Page = SelectedPage.Waiting;
                }
            }
        }

        private void picturebox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && mClickable)
            {
                HandleClick(e);
            }
        }
        private void HandleClick(System.Windows.Forms.MouseEventArgs e)
        {
            switch (mPage)
            {
                case SelectedPage.Index:
                    Rectangle move = new Rectangle(23, 43, 211, 81);
                    Rectangle pm = new Rectangle(179, 149, 74, 40);
                    Rectangle escape = new Rectangle(91, 157, 73, 35);
                    Rectangle tie = new Rectangle(2, 147, 74, 40);

                    if (move.Contains(e.Location))
                    {
                        if (!Struggle())
                        {
                            if (SelectedPokemon.BattleState.encore)
                            {
                                TargetIndex target = TargetIndex.DefaultTarget;
                                switch (SelectedPokemon.LastMove.Target)
                                {
                                    case MoveTarget.随机:
                                        target = TargetIndex.Random;
                                        break;
                                    case MoveTarget.选一:
                                        target = TargetIndex.Random;
                                        break;
                                    case MoveTarget.队友:
                                        target = TargetIndex.TeamFriend;
                                        break;
                                    case MoveTarget.自身:
                                        target = TargetIndex.Self;
                                        break;
                                    case MoveTarget.任选:
                                        target = TargetIndex.Self;
                                        break;
                                }
                                SetPlayerMove(BattleMove.Attack, SelectedPokemon.lastMoveIndex, target);
                            }
                            else
                            {
                                Page = SelectedPage.SelectingMove;
                            }
                        }
                    }
                    else if (pm.Contains(e.Location))
                    {
                        Page = SelectedPage.SelectingPM;
                    }
                    else if (escape.Contains(e.Location))
                    {
                        if (Escape != null)
                        {
                            Escape(this, EventArgs.Empty);
                        }
                    }
                    else if (tie.Contains(e.Location))
                    {
                        if (Tie != null)
                        {
                            Tie(this, EventArgs.Empty);
                        }
                    }
                    break;
                case SelectedPage.SelectingMove:
                    Rectangle cancel = new Rectangle(10, 157, 236, 35);
                    var rectList = new List<Rectangle>();
                    for (int i = 0; i < 4; i++)
                    {
                        rectList.Add(new Rectangle(MovePoint[i], Properties.Resources.Move.Size));
                    }
                    //Rectangle rect1 = new Rectangle(MovePoint[0], Properties.Resources.Move.Size);
                    //Rectangle rect2 = new Rectangle(MovePoint[1], Properties.Resources.Move.Size);
                    //Rectangle rect3 = new Rectangle(MovePoint[2], Properties.Resources.Move.Size);
                    //Rectangle rect4 = new Rectangle(MovePoint[3], Properties.Resources.Move.Size);
                    if (!cancel.Contains(e.Location))
                    {
                        for (int i = 0; i < rectList.Count; i++)
                        {
                            if (rectList[i].Contains(e.Location) && Move(i + 1))
                            {
                                return;
                            }
                        }
                        if (SelectedIndex > 0 && !CanMove(SelectedIndex))
                            SelectedIndex = 0;
                        return;
                    }
                    else
                    {
                        Page = SelectedPage.Index;
                        return;
                    }
                case SelectedPage.SelectingPM:

                    Rectangle cancel_1 = new Rectangle(218, 155, 36, 35);

                    var rect_list = new List<Rectangle>();

                    for (int i = 0; i < 6; i++)
                    {
                        rect_list.Add(new Rectangle(PokemonPoint[i], Properties.Resources.Pokemon.Size));
                    }

                    Pokemon pokemon = null;

                    for (int i = 0; i < 6; i++)
                    {
                        if (rect_list[i].Contains(e.Location))
                        {
                            pokemon = MyTeam.Pokemons[i];
                            break;
                        }
                    }

                    if (pokemon != null && ShowPokemonInfo != null)
                    {
                        ShowPokemonInfo(pokemon);
                    }

                    if (cancel_1.Contains(e.Location))
                    {
                        if (MustChange()) return;
                        Page = SelectedPage.Index;
                    }
                    else
                    {
                        for (int i = 1; i < 6; i++)
                        {
                            if (rect_list[i].Contains(e.Location))
                            {
                                ChangePokemon((byte)(i + 1));
                                break;
                            }
                        }
                    }

                    break;
            }
        }

        private bool CanChange()
        {
            if (SelectedPokemon.BattleState.pass || SelectedPokemon.HealthPower == 0)
                return true;
            if (SelectedPokemon.GetItem() != Item.ShedShell)
            {
                if (SelectedPokemon.BattleState.constraint)
                {
                    MessageBox.Show("你的Pokemon被束缚,现在无法交换", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
                else if (SelectedPokemon.BattleState.ingrain)
                {
                    MessageBox.Show("你的Pokemon已经扎根,现在无法交换", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
                else
                {
                    foreach (Pokemon pm in MyGroup.Opponent.SelectedPokemon)
                    {
                        if (pm.HealthPower > 0)
                        {
                            if ((pm.GetSelTrait() == Trait.ShadowTag && SelectedPokemon.GetSelTrait() != Trait.ShadowTag) ||
                               (pm.GetSelTrait() == Trait.ArenaTrap && ((!SelectedPokemon.IsAboveGroud && !SelectedPokemon.HaveType(BattleType.Flying)) || battle.Ground.Gravity)) ||
                               (pm.GetSelTrait() == Trait.MagnetPull && SelectedPokemon.HaveType(BattleType.Steel)))
                            {
                                MessageBox.Show("你的Pokemon被对手的特性所束缚,现在无法交换", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                return false;
                            }
                        }
                    }
                }
            }
            return true;
        }
        //private Pokemon GetPokemon(byte index)
        //{
        //    return MyTeam.Pokemons[index - 1];
        //    //int index2 = index;
        //    //if (battle.Mode == BattleMode.Double_4P && playerIndex % 2 == 0)
        //    //    index2 += 6;
        //    //return MyTeam.GetPokemonByIndex(index2 - 1);
        //}
        private void ChangePokemon(byte index)
        {
            Pokemon pm = MyTeam.Pokemons[index - 1];

            if (pm == null || pm.HealthPower == 0 || MyGroup.SelectedPokemon.Contains(pm) || _swapPokemon.Contains(index))
                return;

            if (SelectedIndex == index)
            {
                if (!CanChange())
                    return;
                if (SelectedPokemon.HealthPower == 0)
                {
                    SetPlayerMove(BattleMove.DeathSwap, index, TargetIndex.DefaultTarget);
                }
                else if (SelectedPokemon.BattleState.pass)
                {
                    SetPlayerMove(BattleMove.PassSwap, index, TargetIndex.DefaultTarget);
                }
                else
                {
                    SetPlayerMove(BattleMove.SwapPokemon, index, TargetIndex.DefaultTarget);
                }
            }
            else
            {
                SelectedIndex = index;
            }
        }
        private bool MustChange()
        {
            return SelectedPokemon.HealthPower == 0 || SelectedPokemon.BattleState.pass;
        }

        private bool CanMove(int index)
        {
            var move = SelectedPokemon.GetSelMove(index);

            if (SelectedPokemon.BattleState.taunt && move.Data.Category == MoveCategory.变化)
            {
                MessageBox.Show(SelectedPokemon.NickName + "被挑拨不能使用辅助技能", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }
            if (SelectedPokemon.BattleState.torment && SelectedPokemon.lastMoveIndex == index)
            {
                MessageBox.Show(SelectedPokemon.NickName + "被寻衅不能连续使用相同技能", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }
            if ((SelectedPokemon.UsedItem.IsChoiceItem()) && SelectedPokemon.lastMoveIndex != index)
            {
                MessageBox.Show(SelectedPokemon.NickName + "携带了专爱道具只能使用相同技能", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }
            if (battle.Ground.Gravity && (move.Data.Effect == MoveEffect.电磁浮游 || move.Data.AddEffect2 == MoveAdditionalEffect.飞天后攻击 || move.Data.AddEffect2 == MoveAdditionalEffect.跳起后攻击))
            {
                //GravityCantUseMove
                MessageBox.Show("此技能重力下无法使用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }

            foreach (Pokemon pm in MyGroup.Opponent.SelectedPokemon)
            {
                if ((pm.BattleState.imprison && pm.HaveMove(move.Data.Id)) || SelectedPokemon.BattleState.DisableIndex == index)
                {
                    MessageBox.Show("此技能被封印不能使用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
            }
            return true;
        }
        private bool Move(int index)
        {
            if (SelectedPokemon.GetSelMove(index) == null || SelectedPokemon.GetSelMove(index).PP == 0)
                return true;

            if (SelectedIndex == index)
            {
                TargetIndex target = default(TargetIndex);
                if (GetTarget(index, ref target))
                    SetPlayerMove(BattleMove.Attack, (byte)index, target);
                return true;
            }
            else
            {
                SelectedIndex = index;
                return false;
            }
        }
        private bool Struggle()
        {
            if (SelectedPokemon.NoMoveCanUse())
            {
                DialogResult result = MessageBox.Show("你的Pokemon没有可使用的技能,是否使用挣扎?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    TargetIndex target = default(TargetIndex);
                    if (GetTarget(Battle.StruggleIndex, ref target))
                    {
                        SetPlayerMove(BattleMove.Attack, Battle.StruggleIndex, target);
                    }
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        private bool GetTarget(int index, ref TargetIndex target)
        {
            if (index == Battle.StruggleIndex || SelectedPokemon.GetSelMove(index).Target == MoveTarget.选一 || (SelectedPokemon.GetSelMove(index).Target == MoveTarget.任选 && MyGroup.SelectedPokemon.Count() > 1))
            {
                if (MyGroup.SelectedPokemon.Count() == 1) { target = TargetIndex.Opponent1; return true; }

                bool selfEff = false;
                if (index != Battle.StruggleIndex)
                    selfEff = SelectedPokemon.GetSelMove(index).Target == MoveTarget.任选;
                SelectTargetForm targetDialog = new SelectTargetForm(MyGroup, SelectedPokemon, selfEff);
                DialogResult result = targetDialog.ShowDialog();
                if (result == DialogResult.OK)
                {
                    target = targetDialog.Target;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                switch (SelectedPokemon.GetSelMove(index).Target)
                {
                    case MoveTarget.随机:
                        target = TargetIndex.Random;
                        break;
                    case MoveTarget.队友:
                        target = TargetIndex.TeamFriend;
                        break;
                    case MoveTarget.自身:
                        target = TargetIndex.Self;
                        break;
                    case MoveTarget.任选:
                        target = TargetIndex.Self;
                        break;
                    default:
                        target = TargetIndex.DefaultTarget;
                        break;
                }
                return true;
            }
        }
        private void SetPlayerMove(BattleMove moveValue, byte index, TargetIndex target)
        {
            PlayerBattleMove newMove = new PlayerBattleMove(SelectedPokemonIndex, moveValue, index, target);

            _waitMoveCount--;
            if (_waitMoveCount == 0)
            {
                Moved = true;
                _swapPokemon.Clear();
            }
            else
            {
                if (moveValue == BattleMove.DeathSwap || moveValue == BattleMove.SwapPokemon)
                {
                    _swapPokemon.Add(index);
                }
                mSelectedPMIndex += 1;
                if (moveValue == BattleMove.DeathSwap)
                {
                    Page = SelectedPage.SelectingPM;
                }
                else
                {
                    Page = SelectedPage.Index;
                }

            }
            if (PlayerMoved != null)
            {
                PlayerMoved(newMove);
            }
            if (!Moved)
            {
                if (!SelectedPokemon.CanChooseMove)
                {
                    SetPlayerMove(BattleMove.Attack, 0, TargetIndex.DefaultTarget);
                }
                else
                {
                    if (StartShake != null)
                    {
                        StartShake(this, EventArgs.Empty);
                    }
                }
            }
        }

        private Pokemon[] _selectedPokemons;
        private PokemonIndex SelectedPokemonIndex
        {
            get { return battle.GetPokemonIndex(SelectedPokemon); }
        }
        public Pokemon SelectedPokemon
        {
            get { return _selectedPokemons[mSelectedPMIndex - 1]; }
        }

        private int _waitMoveCount;

        private List<int> _swapPokemon = new List<int>();
        public void SetTurnResult(TurnResult result, Pokemon[] pokemons)
        {
            _selectedPokemons = pokemons;
            if (battle.Ended)
            {
                battle = null;
                return;
            }
            if (_selectedPokemons.Length == 0)
                return;
            mSelectedPMIndex = 1;
            mSelectedIndex = 0;
            Moved = false;
            if (!result.TurnComplete)
            {
                if (result.DeadPokemons.Count > 0)
                {
                    int deadCount = result.DeadPokemons.Count(p => _selectedPokemons.Contains(p));
                    if (deadCount > 0)
                    {
                        if (!(SelectedPokemon.HealthPower == 0))
                        {
                            mSelectedPMIndex = 2;
                        }
                        _waitMoveCount = Math.Min(deadCount, _selectedPokemons.Length);
                        Page = SelectedPage.SelectingPM;
                    }
                    else
                    {
                        Moved = true;
                    }
                }
                else
                {
                    if (_selectedPokemons.Contains(result.PassPokemon))
                    {
                        if (!SelectedPokemon.BattleState.pass)
                        {
                            mSelectedPMIndex = 2;
                        }
                        Page = SelectedPage.SelectingPM;
                        _waitMoveCount = 1;
                        if (StartShake != null)
                        {
                            StartShake(this, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        Moved = true;
                    }
                }
            }
            else
            {
                _waitMoveCount = _selectedPokemons.Length;
                Page = SelectedPage.Index;
                if (!SelectedPokemon.CanChooseMove)
                {
                    SetPlayerMove(BattleMove.Attack, 0, TargetIndex.DefaultTarget);
                }
                else
                {
                    if (StartShake != null)
                    {
                        StartShake(this, EventArgs.Empty);
                    }
                }
            }
        }

        public BattleGroup MyGroup
        {
            get { return MyTeam.Group; }
        }

        public BattleTeam MyTeam { get; private set; }

        public static Point[] MovePoint = { new Point(2, 26), new Point(130, 26), new Point(2, 90), new Point(130, 90) };
        public static Point[] PokemonPoint = { new Point(1, 2), new Point(129, 9), new Point(1, 50), new Point(129, 57), new Point(1, 98), new Point(129, 105) };
    }
}
